/*
 * clients.c
 *
 *  Created on: 2012. 4. 12.
 *      Author: jphong
 */
#include	<string.h>
#include	<stdlib.h>
#include	"clients.h"

#define MAXLINE	4096

static Client *clientList = NULL;
static Client *freeList = NULL;

Client *getClientList() {
	return (clientList);
}

char *getUser(const Client *client) {
	if (client->user[0] == '\0')
		return (NULL);
	return (client->user);
}

int getSocket(const Client *client) {
	if (client == NULL)
		return (-1);
	else
		return (client->connfd);
}

Client *findClient(const char *user) {
	Client *client;

	for (client = clientList; client != NULL; client = client->next) {
		if (!strcmp(client->user, user))
			return (client);
	}
	return (NULL);
}

/* Create a client and insert it to clientList
 * Returns: pointer to client node
 *          NULL if couldn't create (Connection should be closed and rejected)
 */
Client *createClient(int connfd) {
	Client *c;

	if (freeList == NULL) {
		// If freeList is empty, allocate memory for a client.
		if (
			   ((c = (Client *) malloc(sizeof(Client))) != NULL)
			&& ((c->user = (char *) malloc((size_t) MAXID)) != NULL)
			&& ((c->ipaddr = (char *) malloc((size_t) MAXID)) != NULL)
			&& ((c->readBuffer = (ReadBuffer *) createRbuf(MAXLINE)) != NULL)
			);// successful memory allocation
		else
			return (NULL); // Not enough memory. return NULL
	} else {
		// Get a client node from freeList
		c = freeList;
		freeList = freeList->next;
	}

	// Initialize the client node
	c->connfd = connfd;
	*(c->user) = '\0';

	initRbuf(c->readBuffer);

	// Insert the client node in front of clientList
	c->next = clientList;
	clientList = c;

	return (c); // returns pointer to the client node
}

/*
 * 	Destroy the client. Just put into freeList for reuse
 */
void destroyClient(Client *c) {
	Client *cur, **pre;

	// remove the client from clientList

	for (pre = &clientList, cur = clientList; (cur != c); pre = &(cur->next), cur = cur->next)
		; // find predecessor
	*pre = c->next; //remove the client

	// insert it to the front of freeList
	c->next = freeList;
	freeList = c;
}

ssize_t readClient(Client *client) {
	return (readBuf(client->readBuffer, client->connfd));
}
